package com.jialiang.yojcodesandbox.controller;

import com.jialiang.yojcodesandbox.enums.QuestionSubmitLanguageEnum;
import com.jialiang.yojcodesandbox.model.ExecuteCodeRequest;
import com.jialiang.yojcodesandbox.model.ExecuteCodeResponse;
import com.jialiang.yojcodesandbox.service.CodeSandbox;
import com.jialiang.yojcodesandbox.service.factory.CodeSandboxFactory;
import com.jialiang.yojcodesandbox.utils.SignUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

@Slf4j
@RestController
@RequestMapping("/")
public class MainController {

    // 访问密钥
    @Value("${codesandbox.accessKey}")
    private String accessKey;

    // 私密密钥
    @Value("${codesandbox.secretKey}")
    private String secretKey;

    /**
     * 执行用户提交代码
     */
    @PostMapping("/executeCode")
    ExecuteCodeResponse executeCode(@RequestBody ExecuteCodeRequest executeCodeRequest,
                                    HttpServletRequest request, HttpServletResponse response) {
        log.info("沙箱请求数据：{}", executeCodeRequest);
        if (executeCodeRequest == null) {
            throw new RuntimeException("请求参数为空");
        }
        // 1.从请求头获取参数
        String requestAccessKey = request.getHeader("accessKey");
        String nonce = request.getHeader("nonce");
        String timestamp = request.getHeader("timestamp");
        String sign = request.getHeader("sign");
        String body = request.getHeader("body");
        // 解决参数乱码问题
        try {
            body = URLDecoder.decode(body, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        // 2.权限校验
        if (!requestAccessKey.equals(accessKey)) {
            response.setStatus(403);
            return null;
        }

        // todo 3.校验随机数 nonce
        // if (Long.parseLong(nonce) > 10000) {
        //     response.setStatus(403);
        //     return null;
        // }

        // 4.校验时间戳与当前时间的差距，不能超过 5 分钟
        long currentTime = System.currentTimeMillis();
        long timeDifference = currentTime - Long.parseLong(timestamp);
        if (timeDifference > 1000 * 60 * 5) {
            response.setStatus(403);
            return null;
        }

        // 5. 签名认证
        String serverSign = SignUtils.genSign(body, secretKey);
        if (!sign.equals(serverSign)) {
            response.setStatus(403);
            return null;
        }

        // 调用原生代码沙箱
        // ExecuteCodeResponse executeCodeResponse = javaNativeCodeSandbox.executeCode(executeCodeRequest);
        QuestionSubmitLanguageEnum languageEnum = QuestionSubmitLanguageEnum.getEnumByValue(executeCodeRequest.getLanguage());
        CodeSandbox codeSandbox = CodeSandboxFactory.getInstance(languageEnum);
        ExecuteCodeResponse executeCodeResponse = codeSandbox.executeCode(executeCodeRequest);
        log.info("沙箱响应信息：{}", executeCodeResponse);
        return executeCodeResponse;
    }

}
